﻿#region Copyright RenGuiYou. All rights reserved.
//=====================================================
// PandoraFrameWork
// Author:      RenGuiyou
// Feedback: 	mailto:750539605@qq.com
//=====================================================
#endregion

using System;
using System.Collections.Generic;
using Pandora;
using UnityEditor;
using UnityEngine;

// ReSharper disable UnusedMember.Local
// ReSharper disable MemberCanBePrivate.Local
namespace PandoraEditor.Window
{
    [InitializeOnLoad]
    public abstract class ConfigWindowBase : EditorWindow
    {
        private class Styles
        {
            public GUIStyle categoryLabel;
            public GUIStyle categoryBG;
            public GUIStyle categoryScrollView;
            public GUIStyle header;
            public GUIStyle helpLine;

            public Styles()
            {
                categoryLabel = new GUIStyle("PreferencesSection");
                categoryLabel.onNormal.textColor = Color.white;
                categoryBG = new GUIStyle("CN EntryBackEven");
                helpLine = new GUIStyle(EditorStyles.label);
                helpLine.wordWrap = true;
                categoryScrollView = "PreferencesSectionBox";
                categoryScrollView = new GUIStyle(categoryScrollView);
                RectOffset overflow = categoryScrollView.overflow;
                int sourceBottom = overflow.bottom;
                overflow.bottom += 1;
                header = new GUIStyle(EditorStyles.largeLabel);
                header.fontStyle = FontStyle.Bold;
                header.fontSize = 18;
                header.margin.top = 10;
                header.margin.left += sourceBottom + 1;
            }
        }

        private class Section
        {
            public string name;
            public bool hasHelper;
            public GUIContent content;
            public OnGUIDelegate drawAction;
            public Action helpAction;

            public Section(string name, OnGUIDelegate guiFunc)
            {
                this.name = name;
                content = new GUIContent(name);
                drawAction = guiFunc;
                hasHelper = false;
            }

            public Section(string name, OnGUIDelegate guiFunc, Action helpAction)
            {
                this.name = name;
                content = new GUIContent(name);
                drawAction = guiFunc;
                hasHelper = true;
                this.helpAction = helpAction;
            }
        }

        private static Styles m_Styles;
        private Vector2 m_SelectedScrollPos;
        private bool m_RefreshCustomPreferences;
        private delegate void OnGUIDelegate();
        private List<Section> m_Sections;
        private int m_CategoryIndex = 0;


        protected void OnEnable()
        {
            m_Sections = new List<Section>();
            Register();
            m_RefreshCustomPreferences = true;
        }

        protected abstract void Register();

        protected void RegisterCategory<C>() where C : ConfigCategory, new()
        {
            C t = new C();
            t.OnInit();
            m_Sections.Add(t.hasHelper ? new Section(t.name, t.DrawAction, t.OnHelpAction) : new Section(t.name, t.DrawAction));
        }

        public void OnGUI()
        {
            if (m_RefreshCustomPreferences)
            {
                AddCustomSections();
                m_RefreshCustomPreferences = false;
            }
            EditorGUIUtility.labelWidth = 160;
            if (m_Styles == null)
                m_Styles = new Styles();
            GUILayout.BeginHorizontal();
            GUILayout.BeginVertical(m_Styles.categoryScrollView, GUILayout.Width(130f));
            GUILayout.Space(10f);
            GUIContent gUIContent;
            Rect rect;
            for (int i = 0; i < m_Sections.Count; i++)
            {
                var section = m_Sections[i];
                gUIContent = section.content;
                rect = GUILayoutUtility.GetRect(gUIContent, m_Styles.categoryLabel, GUILayout.ExpandWidth(true));
                if (m_CategoryIndex == i && Event.current.type == EventType.Repaint)
                {
                    m_Styles.categoryBG.Draw(rect, false, false, true, false);
                }
                EditorGUI.BeginChangeCheck();
                if (GUI.Toggle(rect, m_CategoryIndex == i, gUIContent, m_Styles.categoryLabel))
                {
                    m_CategoryIndex = i;
                    UserSetting.SaveAll();
                    BuildSetting.SaveAll();
                }
                if (EditorGUI.EndChangeCheck())
                {
                    GUIUtility.keyboardControl = 0;
                }
            }
            var current = m_Sections[Mathf.Clamp(m_CategoryIndex, 0, m_Sections.Count - 1)];
            GUILayout.FlexibleSpace();
            GUILayout.BeginVertical(GUILayout.Height(30f));
            gUIContent = new GUIContent(UserSetting.version);
            rect = GUILayoutUtility.GetRect(gUIContent, m_Styles.categoryLabel, GUILayout.ExpandWidth(true));
            EditorGUI.LabelField(rect, UserSetting.version, m_Styles.categoryLabel);
            GUILayout.EndVertical();
            GUILayout.EndVertical();
            GUILayout.Space(10f);
            GUILayout.BeginVertical();
            GUILayout.BeginHorizontal();
            GUILayout.Label(current.name, m_Styles.header);
            if (current.hasHelper && GUILayout.Button(new GUIContent("?", "Get help on " + current.name), GUILayout.Width(20f)))
            {
                current.helpAction();
            }
            GUILayout.EndHorizontal();
            if (current.hasHelper)
            {
                GUILayout.Space(10f);
            }
            m_SelectedScrollPos = GUILayout.BeginScrollView(m_SelectedScrollPos);
            current.drawAction();
            GUILayout.Space(5f);
            GUILayout.EndScrollView();
            GUILayout.EndVertical();
            GUILayout.EndHorizontal();
        }

        private void AddCustomSections()
        {
            var list = PdrAssemblyHelper.GetAttributeMethod<PdrPreference>();
            for (int i = 0; i < list.Count; i++)
            {
                OnGUIDelegate onGUIDelegate = Delegate.CreateDelegate(typeof(OnGUIDelegate), list[i].methodInfo) as OnGUIDelegate;
                if (onGUIDelegate != null)
                {
                    m_Sections.Add(new Section(list[i].attribute.name, onGUIDelegate));
                }
            }
        }
    }
}